package com.sduept.nwld.dataserver.manager.etl;

import com.sduept.bigdata.fault.common.ParamDesc;
import com.sduept.bigdata.fault.entity.FaultRecord;
import com.sduept.bigdata.fault.entity.FaultReportMain;
import com.sduept.bigdata.fault.entity.FaultReportStationDetail;
import com.sduept.bigdata.fault.enums.RegexTypeEnum;
import com.sduept.bigdata.fault.manager.FaultRecordPersistManager;
import com.sduept.bigdata.fault.manager.FaultRecordQueryManager;
import com.sduept.bigdata.fault.parser.entity.StandardLibrary;
import com.sduept.cim.model.extend.LineSegment;
import com.sduept.cim.model.wires.DcLinesegment;
import com.sduept.core.ParamManager;
import com.sduept.core.dao.SuperDAO;
import com.sduept.core.entity.SystemParameter;
import com.sduept.bigdata.weather.map.MapDataCache;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.dataserver.model.daily.Runlog;
import com.sduept.nwld.dataserver.util.CimUtils;
import com.sduept.utils.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class FaultETLDataManager {

	@Autowired
	SuperDAO dao;
	@Autowired
	ParamManager pc;
	@Autowired
	CimManager cm;
	@Autowired
	MapDataCache cache;
	@Autowired
	FaultRecordPersistManager fm;
	@Autowired
	FaultRecordQueryManager fqManager;

	public static final String DEFAULT_DATA_REGEX = "[0-9]{1,2}[:;：；][0-9]{1,2}";
	public static final String DEFAULT_EMPTY_RESULT = "";
	public static final String SIGN_TIME_MINUTE_SECOND = "00:00";
	public static final String SIGN_NUMBER_REGEX = "[^.^\\d]";
	public static final String SIGN_WAVE_RANG = "故障录波测距";
	public static final String SIGN_TRAVEL_RANG = "行波测距";
	public static final String SIGN_PROTECT_ACTION_CONDITION = "保护动作情况";
	public static final String SIGN_PROTECT_RANGING_REGEX = "\n";// split 依据
	public static final String SIGN_PROTECT_ONE = "第一套";
	public static final String SIGN_PROTECT_TWO = "第二套";
	public static final String SIGN_PROTECT_THREE = "第三套";
	public static final String SIGN_VOLTAGE_REGEX = "[0-9]{2,3}kV";
	public static final String SIGN_LINE = "线路";
	public static final String SIGN_RESULT_FAULT = "巡线结果";
	public static final String SIGN_DC_PHASE_ONE = "极一";
	public static final String SIGN_DC_PHASE_TWO = "极二";
	public static final String DEFAULT_SPLIT_REGEX = "。";
	public static final String SIGN_DC_LINE = "直流";
	public static final String SIGN_AC_LINE = "交流";
	public static final String REGEX_TIME_HOUR_MINEUTE_SECOND="[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}";
	private static final String SIGN_RANGING = "测距";

	
	
	public void extracFaultRecord(Runlog record,Map<String,List<StandardLibrary>> map) throws Exception{
		
	}
	public void extracFaultResult(Runlog record,Map<String,List<StandardLibrary>> map) throws Exception{
		
	}
	public void extracFaultProcess(Runlog record,Map<String,List<StandardLibrary>> map)throws Exception{
		
	}
	public String[] getRanging(String subName,String desc,Map<String, List<StandardLibrary>> map){
		return null;
	}

	/**
	 * 根据巡线结果 更新数据
	 * 
	 * @param content
	 * @param date
	 */
	public void updateByInspectionResults(String content, Date date, Map<String, List<StandardLibrary>> map) {
		LineSegment line = null;
		// 电压等级
		String vol = find0("[0-9]{3,}kV", content);
		if (StringUtils.isNotEmpty(vol)) {
			vol = vol.replace("kV", "");
		}
		// 线路名称
		String lineName = null;
		if (content.contains(SIGN_DC_PHASE_ONE) || content.contains(SIGN_DC_PHASE_TWO)) {
			// 直流故障
			List<StandardLibrary> list = map.get(RegexTypeEnum.DCLINE_DATA_REGEX.getCode());
			lineName = getFirstMatcher(content, list);
			if (StringUtils.isNotEmpty(lineName)) {
				line = queryDcLinesegment(lineName);
			}
		} else {
			// 交流故障
			List<StandardLibrary> list = map.get(RegexTypeEnum.ACLINE_DATA_REGEX.getCode());
			lineName = getFirstMatcher(content, list);
			if (StringUtils.isNotEmpty(lineName)) {
				line = queryLineCimId(lineName);
			}
		}

		// 故障时间
		List<StandardLibrary> list = map.get(RegexTypeEnum.RESULT_TIME_REGEX.getCode());
		List<StandardLibrary> timeList = map.get(RegexTypeEnum.SIGN_FAULT_TIME_REGEX.getCode());
		String happenDate = getFirstMatcher(content, list);
		Date faultDate = null;
		String faultDateTime = "";
		// 如果时间可以匹配的到
		if (StringUtils.isNotEmpty(happenDate)) {
			String second = getFaultDate(happenDate, timeList);
			if (StringUtils.isNotEmpty(second)) {
				happenDate = getDateByString(happenDate);
				happenDate = happenDate + ":00";
			} else {
				happenDate = getDateByString(happenDate);
				happenDate = happenDate + "00:00:00";
			}
			faultDateTime = getCurrentYear(date) + "-" + happenDate;
			faultDate = DateUtil.getDateByString(faultDateTime, DateUtil.pattern_ymdhms);
			if (faultDate.getTime() > date.getTime()) {
				faultDateTime = (getCurrentYear(date) - 1) + "-" + happenDate;
				faultDate = DateUtil.getDateByString(faultDateTime, DateUtil.pattern_ymdhms);
			}
		}
		// 查找到记录
		if (faultDate != null) {
			Date[] dates = null;
			if (faultDateTime.endsWith("00:00:00")) {
				dates = getOneDates(faultDate);
			} else {
				dates = getnearlyDates(faultDate);
			}
			List<FaultRecord> findByCondition = new ArrayList<FaultRecord>();
			if (null != line) {
				findByCondition = fqManager.findFaultByTimeDeviceId(dates[0], dates[1], line.getId());
			} else {
				findByCondition = fqManager.findFaultByTimeDeviceName(lineName, dates[0], dates[1]);
			}
			String reasonType = getReason(content);
			for (FaultRecord record : findByCondition) {
				if (StringUtils.isEmpty(record.getRemark())) {
					record.setRemark(content);
				} else if (!record.getRemark().contains(content)) {
					record.setRemark(record.getRemark() + "\n" + content);
				}
				// 获取杆塔
				updateST(record, map);
				if (StringUtils.isNotEmpty(reasonType) && StringUtils.isEmpty(record.getFaultReson())) {
					record.setFaultReson(reasonType);
				}
			}
		} else {
			// 没有故障时间 找到最近一条缺陷记录
			Date[] dates = getOneDates(date);
			List<FaultRecord> findByCondition = null;
			if (null != line) {
				findByCondition = fqManager.findFaultByTimeDeviceId(dates[0], dates[1], line.getId());
			} else {
				findByCondition = fqManager.findFaultByTimeDeviceName(lineName, dates[0], dates[1]);
			}
			if (findByCondition != null && findByCondition.size() > 0) {
				for(FaultRecord record:findByCondition){
					if (StringUtils.isEmpty(record.getRemark())) {
						record.setRemark(content);
					} else if (!record.getRemark().contains(content)) {
						record.setRemark(record.getRemark() + "\n" + content);
					}
					updateST(record, map);
					String reasonType = getReason(content);
					if (StringUtils.isNotEmpty(reasonType) && StringUtils.isEmpty(record.getFaultReson())) {
						record.setFaultReson(reasonType);
					}
				}
			}
		}

	}

	/**
	 * 更新 杆塔
	 * 
	 * @param record
	 */
	public void updateST(FaultRecord record, Map<String, List<StandardLibrary>> map) {
		String startST = getST(record.getRemark(), map);
		if (StringUtils.isNotEmpty(startST)) {// 如果
			if (!startST.contains("-")) {
				record.setStartPole(Integer.parseInt(startST));
			} else {
				String[] split = startST.split("-");
				record.setStartPole(Integer.parseInt(split[0]));
				record.setEndPole(Integer.parseInt(split[1]));
			}

		}
	}

	/**
	 * 根据巡线结果 获取杆塔号
	 * 
	 * @param s
	 * @return
	 */
	private String getST(String s, Map<String, List<StandardLibrary>> map) {
		if (StringUtils.isEmpty(s)) {
			return null;
		}
		String[] split = s.split("\n");
		List<StandardLibrary> list = map.get(RegexTypeEnum.SIGN_TOWER_REGEX.getCode());
		if (split.length == 1) {
			if(!s.contains(SIGN_RESULT_FAULT)){
				return null;
			}
			s = s.substring(s.indexOf(SIGN_RESULT_FAULT));
			s = s.replaceAll(SIGN_VOLTAGE_REGEX, "");// 去除电压等级导致杆塔匹配错误
			String startST = getFirstMatcher(s, list);
			return startST;
		} else {
			for (String st : split) {
				if (st.contains("无异常")) {
					continue;
				} else {
					if (st.contains(SIGN_RESULT_FAULT)) {
						st = st.substring(st.indexOf(SIGN_RESULT_FAULT));
						st = st.replaceAll(SIGN_VOLTAGE_REGEX, "");// 去除电压等级导致杆塔匹配错误
						String startST = getFirstMatcher(s, list);
						return startST;
					}

				}
			}
		}
		return null;
	}

	/**
	 * 此方法根据故障记录的测距更新故障报告
	 * 
	 * @param record
	 */
	public void updateFaultReportByFaultRecord(FaultRecord record, String str) {
		if (!SIGN_LINE.equals(record.getEtype())) {
			return;
		}
		if (str == null) {
			return;
		}
		List<FaultReportMain> rtn = dao.findByCondition(FaultReportMain.class, "faultRecord.id=?", record.getId());
		if (rtn.size() == 0) {
			return;
		}
		FaultReportMain reportMain = rtn.get(0);
		Set<FaultReportStationDetail> faultReportStationDetails = reportMain.getFaultReportStationDetails();
		String[] stationData = str.split("：");
		if (stationData == null || stationData.length != 2) {
			return;
		}
		for (FaultReportStationDetail stationDetail : faultReportStationDetails) {
			if (CimUtils.stationNameMatching(stationDetail.getStationName(), stationData[0].toString(), true)) {
				String[] datas = stationData[1].toString().split("，");
				if (datas == null) {
					continue;
				}
				for (String s1 : datas) {
					if (s1.contains(SIGN_PROTECT_ONE)) {// 主一保护
						String distance = getDistance(SIGN_PROTECT_ONE, s1);
						if (StringUtils.isNotEmpty(distance) && stationDetail.getManualFaultRangingFirst() == null) {
							stationDetail.setManualFaultRangingFirst(Double.valueOf(distance));
						}
					} else if (s1.contains(SIGN_PROTECT_TWO)) {// 主二保护
						String distance = getDistance(SIGN_PROTECT_TWO, s1);
						if (StringUtils.isNotEmpty(distance) && stationDetail.getManualFaultRangingSecond() == null) {
							stationDetail.setManualFaultRangingSecond(Double.valueOf(distance));
						}
					} else if (s1.contains(SIGN_PROTECT_THREE)) {// 主三保护
						String distance = getDistance(SIGN_PROTECT_THREE, s1);
						if (StringUtils.isNotEmpty(distance) && stationDetail.getManualFaultRangingThird() == null) {
							stationDetail.setManualFaultRangingThird(Double.valueOf(distance));
						}
					} else if (s1.contains(SIGN_WAVE_RANG)) {// 录波测距
						String distance = getDistance(SIGN_WAVE_RANG, s1);
						if (StringUtils.isNotEmpty(distance) && stationDetail.getManualRangingWave() == null) {
							stationDetail.setManualRangingWave(Double.valueOf(distance));
						}
					} else if (s1.contains(SIGN_TRAVEL_RANG)) {// 行波测距
						String distance = getDistance(SIGN_TRAVEL_RANG, s1);
						if (StringUtils.isNotEmpty(distance) && stationDetail.getTravelingWave() == null) {
							stationDetail.setTravelingWave(Double.valueOf(distance));
						}
					}
				}
				break;
			}
		}
		dao.createOrUpdate(reportMain, FaultReportMain.class);
	}

	/**
	 * 获取距离
	 * 
	 * @param regex
	 * @param str
	 * @return
	 */
	private String getDistance(String regex, String str) {
		String rtn = null;
		if (str.contains(regex)) {
			rtn = str.replaceAll(SIGN_NUMBER_REGEX, "");
		}
		return rtn;
	}

	/**
	 * 获取 时：分
	 * 
	 * @param str
	 * @param list
	 * @return
	 */
	public String getFaultDate(String str, List<StandardLibrary> list) {
		String rtn = DEFAULT_EMPTY_RESULT;
		if (null == list || list.size() == 0) {
			rtn = find0(DEFAULT_DATA_REGEX, str);
		} else {
			rtn = getFirstMatcher(str, list);
		}
		if (StringUtils.isEmpty(rtn)) {
			return DEFAULT_EMPTY_RESULT;
		}
		rtn = rtn.replaceAll("[:;：；]", ":");
		return rtn;
	}

	/**
	 * 获取故障类型
	 * 
	 * @param s
	 * @return
	 */
	public String getFaultType(String s, String phase) {
		if (StringUtils.isEmpty(phase)) {
			return null;
		} else if (phase.length() == 1 && s.contains("重合") && s.contains("不成功")) {
			return "单永";
		} else if (phase.length() == 1 && s.contains("重合") && s.contains("成功")) {
			return "单瞬";
		} else if (s.contains("强送不成功")) {
			return "永久性故障";
		} else if (phase.length() == 2 && s.contains("相间")) {
			return "两相相间";
		} else if (phase.length() == 2 && s.contains("接地")) {
			return "两相接地";
		} else if (phase.length() == 3) {
			return "三相短路";
		}
		return null;
	}

	/**
	 * 获取故障时间 兼容以下情况：
	 *  ① 7月30日 15:48的情况
	 *  ② 30日 15:48的情况
	 *  ③ 15:48的情况
	 * 
	 * @param desc
	 * @param recordDate
	 * @param list
	 * @return
	 */
	public Date getFaultTime(String desc, Date recordDate, List<StandardLibrary> list) {
		Date result = null;
		String time = getFaultDate(desc, list);
		if (StringUtils.isEmpty(time)) {
			return result;
		}
		String faultTime=null;
		//如果是{1,}月{1,}日 的情况
		if(time.contains("月")&&time.contains("日")){
			String[] split = time.split("日");
			String monthDay = getDateByString(split[0]);
			int currentYear = getCurrentYear(recordDate);
			faultTime=currentYear+"-"+monthDay+" "+(split[1].replace(" ", ""))+ ":00";
		}else if(time.contains("日")){
			String[] split = time.split("日");
			int currentYear = getCurrentYear(recordDate);
			int month = getCurrentMonth(recordDate);
			faultTime=currentYear+"-"+month+"-"+split[0]+" "+(split[1].replace(" ", ""))+ ":00";
		}else{
			String date = DateUtil.getStringDate(recordDate, DateUtil.pattern_ymd);
			if(time.matches(REGEX_TIME_HOUR_MINEUTE_SECOND)){
				faultTime = date + " " + time;
			}else{
				faultTime = date + " " + time + ":00";
			}
		}
		result = DateUtil.getDateByString(faultTime, DateUtil.pattern_ymdhms);
		if (result.getTime() > recordDate.getTime()) {
			result = getYesterDay(result);
		}
		return result;
	}

	/**
	 * 返回正则表达式第1个结果
	 * 
	 * @param regex
	 * @param str
	 * @return
	 */

	public static String find0(String regex, String str) {
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(str);
		while (m.find()) {
			return m.group(0);
		}
		return DEFAULT_EMPTY_RESULT;
	}

	/**
	 * 返回正则表达式第2个结果
	 * 
	 * @param regex
	 * @param str
	 * @return
	 */
	public static String find1(String regex, String str) {
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(str);
		while (m.find()) {
			return m.group(1);
		}
		return DEFAULT_EMPTY_RESULT;
	}

	/**
	 * 返回正则表达式的所有结果
	 * 
	 * @param regex
	 * @param source
	 * @return
	 */
	public List<String> getMatchers(String regex, String source) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(source);
		List<String> list = new ArrayList<>();
		while (matcher.find()) {
			list.add(matcher.group());
		}
		return list;
	}

	public boolean isContainStation(String s, String subName) {
		if (StringUtils.isEmpty(s)) {
			return false;
		} else {
			String[] split = s.split("；");
			for (String str : split) {
				String[] split2 = str.split("：");
				if (split2.length > 0) {
					String name = split2[0];
					if (CimUtils.stationNameMatching(name, subName) || CimUtils.isContain(name, subName) || CimUtils.isContain(subName, name)) {
						return true;
					}
				}
			}
		}
		return false;
	}


	/**
	 * 获取指定日期的前一天
	 * 
	 * @param date
	 * @return
	 */
	public Date getYesterDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		date = calendar.getTime();
		return date;
	}


	/**
	 * 获取第一个匹配的结果
	 * 
	 * @param str
	 * @param list
	 * @return
	 */
	public String getFirstMatcher(String str, List<StandardLibrary> list) {
		String result = DEFAULT_EMPTY_RESULT;
		for (StandardLibrary tmp : list) {
			String string = find0(tmp.getName(), str);
			if (StringUtils.isNotEmpty(string)) {
				return string;
			}
		}
		return result;
	}

	/**
	 * 获取第二 个匹配的结果
	 * 
	 * @param str
	 * @param list
	 * @return
	 */
	public String getSecondMatcher(String str, List<StandardLibrary> list) {
		String result = DEFAULT_EMPTY_RESULT;
		for (StandardLibrary tmp : list) {
			String string = find1(tmp.getName(), str);
			if (StringUtils.isNotEmpty(string)) {
				return string;
			}
		}
		return result;
	}

	/**
	 * 获取指定时间上下一分钟时间 dates[0] 上一分钟 ，dates[1] 下一分钟
	 * 
	 * @param date
	 * @return
	 */
	public Date[] getnearlyDates(Date date) {
		Date[] result = new Date[2];
		DateTime dateTime = new DateTime(date);
		result[0] = dateTime.minusMinutes(1).toDate();
		result[1] = dateTime.plusMinutes(1).toDate();
		return result;
	}

	/**
	 * 获取指定日期的开始时间 结束时间 eg dates[0] 2018-06-21 00:00:00 dates[1] 2018-06-21
	 * 23:59:59
	 * 
	 * @param date
	 * @return
	 */
	public Date[] getOneDates(Date dt) {
		Date[] result = new Date[2];
		String date = DateUtil.getStringDate(dt, DateUtil.pattern_ymd);
		String start = date + " 00:00:00";
		String end = date + " 23:59:59";
		result[0] = DateUtil.getDateByString(start, DateUtil.pattern_ymdhms);
		result[1] = DateUtil.getDateByString(end, DateUtil.pattern_ymdhms);
		return result;
	}


	public LineSegment queryLineCimId(String lineName) {
		LineSegment rtn = cm.getACLineSegmentByName(lineName, cache.getAcLineIdMapByVoltage(500, null).values());
		return rtn;
	}

	public DcLinesegment queryDcLinesegment(String lineName) {
		DcLinesegment rtn = cm.getDcLineSegmentByName(lineName, null);
		return rtn;
	}

	/**
	 * 获取故障原因
	 * 
	 * @param s
	 * @return
	 */
	public String getReason(String s) {
		Collection<SystemParameter> values = pc.listParamsByPid(ParamDesc.GROUP_FAULT_REASON);
		for (SystemParameter param : values) {
			if (s.contains(param.getDescription())) {
				return param.getDescription();
			}
		}
		return null;
	}

	/**
	 * 把字符串中的月、日替换 eg:06月25日 -> 06-25
	 * 
	 * @param s
	 * @return
	 */
	public String getDateByString(String s) {
		if (s.contains("月")) {
			s = s.replace("月", "-");
		}
		if (s.contains("日")) {
			s = s.replace("日", " ");
		}
		return s;
	}

	/**
	 * 获取当前时间的年份
	 * 
	 * @return
	 */
	public static int getCurrentYear(Date date) {
		DateTime dateTime = new DateTime(date);
		int result = dateTime.getYear();
		return result;
	}
	/**
	 * 获取线路的类型:直流或者交流
	 * @param record
	 * @return
	 */
	public String getLineType(String lineName) {
		if(lineName.contains("直流")||lineName.contains("极一")||lineName.contains("极二")){
			return SIGN_DC_LINE;
		}
		return SIGN_AC_LINE;
	}
	/**
	 * 获取当前时间的月份
	 * 
	 * @return
	 */
	public static int getCurrentMonth(Date date) {
		DateTime dateTime = new DateTime(date);
		int result = dateTime.getMonthOfYear();
		return result;
	}

	/**
	 * 处理测距描述 eg: 主二保护接地距离一段,电流差动动作，选A相，测距29.7km，
	 * 
	 * @param str
	 * @return
	 */
	public String DealWithWaveRanG(String str) {
		if (!str.contains(SIGN_RANGING)) {
			return null;
		}
		String dis = str.substring(str.indexOf(SIGN_RANGING), str.length()).replaceAll(SIGN_NUMBER_REGEX, "");
		return dis;
	}
	
	/**
	 * 根据设备Id，设备名称，调度日志 查询故障记录
	 * @param equipmentId
	 * @param equipment
	 * @param record
	 * @return
	 */
	public List<FaultRecord> getRecords(String equipmentId, String equipment, Runlog record) {
		List<FaultRecord> result = new ArrayList<>();
		Date[] oneDates = getOneDates(record.getTime());
		if (StringUtils.isNotEmpty(equipmentId)) {
			result = fqManager.findFaultByTimeDeviceId(oneDates[0], oneDates[1], equipmentId);
			if (result.size() == 0) {
				List<FaultRecord> list=fqManager.findLtFaultTimeFaultByTimeDeviceId(record.getTime(), equipmentId);
				if (list.size() > 0) {
					result.add(list.get(0));
				}
			}
		} else if (StringUtils.isNotEmpty(equipment)) {
			result = fqManager.findFaultByTimeDeviceName(equipment, oneDates[0], oneDates[1]);
			if (result.size() == 0) {
				List<FaultRecord> list=fqManager.findLtFaultTimeFaultByTimeDeviceName(record.getTime(), equipment);
				if (list.size() > 0) {
					result.add(list.get(0));
				}
			}
		}
		return result;
	}
}
